home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  27.1 KB  |  757 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-2000 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19.  
  20. #define debugBuild 0
  21.  
  22. #if debugBuild
  23. #define debugLevel 2
  24. #define debugStatus(ref, str, val) USBExpertStatusLevel(debugLevel, ref, kCompositeDriverName str, val);
  25. #else
  26. #define debugLevel 5
  27. #define debugStatus(ref, str, val) 
  28. #endif
  29.  
  30. usbCompositePBStruct newInterfacesPB;
  31.  
  32. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  33. {
  34.     paramblock->usbReference = theDeviceRef;
  35.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  36.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  37.     paramblock->pbVersion = kUSBCurrentPBVersion;
  38.     paramblock->usb.cntl.WIndex = 0;             
  39.     paramblock->usbBuffer = nil;        
  40.     paramblock->usbStatus = kUSBNoErr;
  41.     paramblock->usbReqCount = 0;
  42.     paramblock->usbActCount = 0;
  43.     paramblock->usb.cntl.WValue = 0;
  44.     paramblock->usbFlags = 0;
  45. }
  46.  
  47. /*
  48.     This is copied wholesale from the UIM via the hub driver. 
  49.  
  50.   This table contains the list of errata that are necessary for known problems with particular hub
  51.   The format is vendorID, product ID, lowest revisionID needing errata, highest rev needing errata, errataBits
  52.   The result of all matches is ORed together, so more than one entry may match.  Typically for a given errata a
  53.   list of hubs revisions that this applies to is supplied.
  54. */
  55. enum{
  56.     kErrataNoReset = 1
  57.     };
  58.  
  59. typedef struct {
  60.     UInt16                         vendID;
  61.     UInt16                         deviceID;
  62.     UInt16                         revisionLo;
  63.     UInt16                         revisionHi;
  64.     UInt32                         errata;
  65. }ErrataListEntry;
  66.  
  67. static ErrataListEntry    errataList[] = {
  68.  
  69. /* For the Cherry 3 port KB, radar 2358706
  70.  
  71.     With the composite driver doing a reset as its first action
  72.     (fixes a mass storage problem, but sounds like a bad idea)
  73.     the Cherry 3 prot KB does not work at boot, but does if 
  74.     hot plugged. It looks like all the resets at composite
  75.     replacement are sending it screwy. It looks to be 
  76.     working fine, but never gives any status change on its
  77.     interrupt endpoint.
  78.     
  79. */
  80.     {0x046a, 0x001, 0x0000, 0x9999, kErrataNoReset} // Cherry 3 port KB
  81. };
  82.  
  83. #define errataListLength (sizeof(errataList)/sizeof(ErrataListEntry))
  84.  
  85. static UInt32 GetErrataBits(USBDeviceDescriptor *desc)
  86. {
  87.     UInt32                vendID, deviceID, revisionID;
  88.     ErrataListEntry        *entryPtr;
  89.     UInt32                i, errata = 0;
  90.     
  91.     // get this chips vendID, deviceID, revisionID
  92.     vendID = USBToHostWord(desc->vendor);
  93.     deviceID = USBToHostWord(desc->product);
  94.     revisionID = USBToHostWord(desc->devRel);
  95.  
  96.     for(i=0, entryPtr = errataList; i<errataListLength; i++, entryPtr++){
  97.         if (vendID == entryPtr->vendID && deviceID == entryPtr->deviceID &&
  98.             revisionID >= entryPtr->revisionLo && revisionID <= entryPtr->revisionHi){
  99.                 errata |= entryPtr->errata;  // we match, add this errata to our list
  100.         }
  101.     }
  102.     return(errata);
  103. }
  104.  
  105.  
  106. Boolean immediateError(OSStatus err)
  107. {
  108.     return((err != kUSBPending) && (err != kUSBNoErr) );
  109. }
  110.  
  111. void CompositeDeviceInitiateTransaction(USBPB *pb)
  112. {
  113. register usbCompositePBStruct *pCompositePB;
  114. OSStatus myErr;
  115.  
  116.     pCompositePB = (usbCompositePBStruct *)(pb);
  117.  
  118.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  119.         return;
  120.         
  121.     pCompositePB->transDepth++;
  122.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  123.     {
  124.     
  125.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  126.     }
  127.     
  128.     if (pCompositePB->driverRemovalPending)
  129.     {
  130.         pCompositePB->pb.usbRefcon = kReturnFromDriver;
  131.         return;
  132.     }
  133.  
  134.     switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  135.     {
  136.         case kResetDevice:
  137.     debugStatus(pCompositePB->pb.usbReference, ": kResetDevice resetting ", newInterfacesPB.busPowerAvailable);
  138.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  139.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  140.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  141.             myErr = USBResetDevice(pb);
  142.             if(immediateError(myErr))
  143.             {
  144.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  145.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kResetDevice - immediate error", myErr);
  146.             }
  147.             break;
  148.  
  149.         case kGetAConfiguration:
  150.     debugStatus(pCompositePB->pb.usbReference, ": kGetAConfiguration getting ", newInterfacesPB.busPowerAvailable);
  151.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  152.             
  153.             // Find the first configuration with any interface which satisfy the power requirements
  154.             pCompositePB->pb.usbReqCount = newInterfacesPB.busPowerAvailable;             
  155.             pCompositePB->pb.usbClassType = 0;             
  156.             pCompositePB->pb.usbSubclass = 0;             
  157.             pCompositePB->pb.usbProtocol = 0;             
  158.             pCompositePB->pb.usb.cntl.WValue = 0;             
  159.             pCompositePB->pb.usb.cntl.WIndex = 0;             
  160.             pCompositePB->pb.usbOther = 0xff;         // Find primary interface, not alts
  161.             
  162.             
  163.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  164.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  165.             myErr = USBFindNextInterface(pb);
  166.             if(immediateError(myErr))
  167.             {
  168.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  169.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBFindNextInterface (#1) - immediate error", myErr);
  170.             }
  171.             break;
  172.         
  173.         case kSetConfig:
  174.     debugStatus(pCompositePB->pb.usbReference, ": kSetConfig setting ", pCompositePB->currentConfiguration);
  175.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  176.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;
  177.  
  178.             pCompositePB->pb.usbRefcon |= kCompletionPending;            
  179.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  180.             myErr = USBSetConfiguration(pb);
  181.             if(immediateError(myErr))
  182.             {
  183.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  184.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBSetConfiguration - immediate error", myErr);
  185.             }
  186.             break;
  187.             
  188.         case kAllocInterfaces:
  189.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  190.             pCompositePB->pb.usbReqCount = pCompositePB->interfaceCount * sizeof(interface);
  191.     debugStatus(pCompositePB->pb.usbReference, ": kAllocInterfaces allocating ", pCompositePB->pb.usbReqCount);
  192.             
  193.             pCompositePB->pb.usbRefcon |= kCompletionPending;            
  194.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  195.             myErr = USBAllocMem(pb);
  196.             if(immediateError(myErr))
  197.             {
  198.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  199.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBAllocMem - immediate error", myErr);
  200.             }
  201.             break;
  202.                 
  203.         case kGetConfigDesc:
  204.     debugStatus(pCompositePB->pb.usbReference, ": kGetConfigDesc new ", pCompositePB->currentConfiguration);
  205.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  206.  
  207.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;
  208.             pCompositePB->pb.usbBuffer = &pCompositePB->configDescriptor;     // put it here
  209.             pCompositePB->pb.usbReqCount = sizeof(USBConfigurationDescriptor);     // at most this size
  210.  
  211.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  212.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  213.             myErr = USBGetConfigurationDescriptor(pb);
  214.             if(immediateError(myErr))
  215.             {
  216.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  217.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetConfigurationDescriptor - immediate error", myErr);
  218.             }
  219.     
  220.             break;
  221.  
  222.         case kSetRemoteWakeup:            
  223.     debugStatus(pCompositePB->pb.usbReference, ": kSetRemoteWakeup doing", pCompositePB->pb.usbReference);
  224.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  225.             
  226.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);            
  227.             
  228.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetFeature;
  229.             pCompositePB->pb.usb.cntl.WValue = kUSBFeatureDeviceRemoteWakeup; 
  230.             pCompositePB->pb.usb.cntl.WIndex = 0;
  231.             
  232.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  233.             
  234.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  235.             myErr = USBDeviceRequest(pb);
  236.             if(immediateError(myErr))
  237.             {
  238.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  239.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetRemoteWakeup - immediate error", myErr);
  240.             }
  241.             break;
  242.  
  243.         case kNewInterfaceRef:
  244.     debugStatus(pCompositePB->pb.usbReference, ": kNewInterfaceRef new ", pCompositePB->currentInterface);
  245.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  246.             // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
  247.             // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  248.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->currentInterface;
  249.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  250.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  251.  
  252.             myErr = USBNewInterfaceRef(pb);
  253.             if(immediateError(myErr))
  254.             {
  255.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  256.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr);
  257.             }
  258.             break;
  259.  
  260.         case kGetInterfaceDesc:
  261.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc", pCompositePB->interfaces[pCompositePB->interfaceIndex].ref);
  262.             InitParamBlock(pCompositePB->interfaces[pCompositePB->interfaceIndex].ref, &pCompositePB->pb);
  263.             pCompositePB->pb.usb.cntl.WIndex = 0;     // Get me the first one
  264.             pCompositePB->pb.usbOther = kUSBInterfaceDesc;     // Get me an interface descriptor
  265.             pCompositePB->pb.usbBuffer = &pCompositePB->interfaces[pCompositePB->interfaceIndex].desc;     // put it here
  266.             pCompositePB->pb.usbReqCount = sizeof(USBInterfaceDescriptor);     // at most this size
  267.             
  268.             
  269.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc", pCompositePB->interfaces[pCompositePB->interfaceIndex].ref);
  270.     //    *(long *)pCompositePB->pb.usbBuffer = 0;
  271.             
  272.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  273.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  274.             myErr = USBFindNextAssociatedDescriptor(pb);
  275.             if(immediateError(myErr))
  276.             {
  277.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  278.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kGetInterfaceDesc - immediate error", myErr);
  279.             }
  280.             
  281.             break;
  282.  
  283.         case kFindNextInterface:
  284.     debugStatus(pCompositePB->pb.usbReference, ": kFindNextInterface curr ", pCompositePB->currentInterface);
  285.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  286.             
  287.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;             
  288.             // Find the first configuration with any interface which satisfy the power requirements
  289.             pCompositePB->pb.usbReqCount = newInterfacesPB.busPowerAvailable;             
  290.             pCompositePB->pb.usbClassType = 0;             
  291.             pCompositePB->pb.usbSubclass = 0;             
  292.             pCompositePB->pb.usbProtocol = 0;             
  293.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;             
  294.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->currentInterface;             
  295.             pCompositePB->pb.usbOther = 0xff;         // Find primary interface, not alts
  296.             
  297.             
  298.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  299.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  300.             myErr = USBFindNextInterface(pb);
  301.             if(immediateError(myErr))
  302.             {
  303.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  304.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kFindNextInterface - immediate error", myErr);
  305.             }
  306.  
  307.             break;
  308.             
  309.         default:
  310.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  311.             pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  312.             break;
  313.     }
  314.     
  315. // At this point the control is returned to the system.  If a USB transaction
  316. // has been initiated, then it will call the Complete procs
  317. // (below) to handle the results of the transaction.
  318. }
  319.  
  320. void CompositeDeviceCompletionProc(USBPB *pb)
  321. {
  322. register usbCompositePBStruct *pCompositePB;
  323. static entryCounter = 0;
  324.  
  325.     pCompositePB = (usbCompositePBStruct *)(pb);
  326.  
  327.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  328.         return;
  329.         
  330.     pCompositePB->transDepth--;
  331.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  332.     {
  333.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth);
  334.     }
  335.     
  336.     
  337.     
  338.     if(pCompositePB->pb.usbStatus == kUSBDevicePowerProblem)
  339.     { 
  340.         if((pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kGetAConfiguration)
  341.         {
  342.  
  343.             USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": sending power note and giving up", pCompositePB->pb.usbStatus);
  344.             
  345.             USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, kUSB500mAAvailable);  // TC: <USB67>
  346.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  347.             return;
  348.         }
  349.         if((pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kSetConfig)
  350.         {
  351.             USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": kSetConfig gives power problem, must have 0mA to play with", pCompositePB->pb.usbStatus);
  352.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  353.             return;                    
  354.         }
  355.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": power problem in unexpected state", pCompositePB->pb.usbRefcon);
  356.     }
  357.     
  358.     if ((pCompositePB->pb.usbStatus == kUSBEndpointStallErr) && 
  359.         (pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kSetRemoteWakeup){
  360.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Device does not support RemoteWakeup (should look in the descriptor)", pCompositePB->configDescriptor.attributes);
  361.         pCompositePB->pb.usbStatus = kUSBNoErr;
  362.     }
  363.     
  364.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  365.     {
  366.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus);
  367.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  368.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  369.         pCompositePB->retryCount--;
  370.         if (!pCompositePB->retryCount)
  371.         {
  372.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon);
  373.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  374.             return;
  375.         }
  376.     }
  377.     else
  378.     {
  379.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  380.         pCompositePB->retryCount = kCompositeRetryCount;
  381.     }
  382.  
  383.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  384.     {                                                
  385.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  386.         switch(pCompositePB->pb.usbRefcon)
  387.         {
  388.             case kResetDevice:            /* Device is not reset */
  389.     debugStatus(pCompositePB->pb.usbReference, ": kResetDevice reset ", newInterfacesPB.busPowerAvailable);
  390.                 pCompositePB->pb.usbRefcon = kGetAConfiguration;
  391.                 break;
  392.  
  393.             case kGetAConfiguration:
  394.     debugStatus(pCompositePB->pb.usbReference, ": kGetAConfiguration got ", pCompositePB->pb.usb.cntl.WValue);
  395.                 // usb.cntl.WValue has the configuration value
  396.                 // usb.cntl.WIndex has the first interface number
  397.                 
  398.                 pCompositePB->currentConfiguration = pCompositePB->pb.usb.cntl.WValue;
  399.                 pCompositePB->currentInterface = pCompositePB->pb.usb.cntl.WIndex;
  400.                 pCompositePB->interfaceIndex = 0;
  401.                 
  402.                 pCompositePB->pb.usbRefcon = kSetConfig;
  403.  
  404.                 break;
  405.                 
  406.             case kSetConfig:
  407.     debugStatus(pCompositePB->pb.usbReference, ": kSetConfig count ", pCompositePB->pb.usbOther);
  408.                 pCompositePB->interfaceCount = pCompositePB->pb.usbOther;
  409.  
  410.                 pCompositePB->pb.usbRefcon = kAllocInterfaces;
  411.                 break;
  412.                 
  413.             case kAllocInterfaces:
  414.                 
  415.                 if(pCompositePB->pb.usbActCount < pCompositePB->interfaceCount * sizeof(interface))
  416.                 {
  417.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName"kAllocInterfaces - not enough memory allocated", pCompositePB->pb.usbActCount);
  418.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  419.                 }
  420.                 else
  421.                 {
  422.                     pCompositePB->interfaces = pCompositePB->pb.usbBuffer;
  423.                     pCompositePB->pb.usbRefcon = kGetConfigDesc;
  424.                 }
  425.                 break;
  426.  
  427.             case kGetConfigDesc:
  428.     debugStatus(pCompositePB->pb.usbReference, ": kGetConfigDesc ", pCompositePB->pb.usbActCount);
  429.                 if(pCompositePB->pb.usbActCount < kUSBConfigDescriptorLength)
  430.                 {
  431.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kGetConfigDesc - got bad descriptor", pCompositePB->pb.usbActCount);
  432.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  433.                 }
  434.                 else
  435.                 {
  436.                     pCompositePB->pb.usbRefcon = 
  437.                         (pCompositePB->configDescriptor.attributes & kUSBAtrRemoteWakeup) ? kSetRemoteWakeup : kNewInterfaceRef;
  438.                 }            
  439.                 break;
  440.             
  441.  
  442.             case kSetRemoteWakeup:            
  443.     debugStatus(pCompositePB->pb.usbReference, ": kSetRemoteWakeup ", pCompositePB->pb.usbReference);
  444.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  445.                 break;
  446.                 
  447.             case kNewInterfaceRef:
  448.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  449.                 /* save the new interface ref for this interface */
  450.     debugStatus(pCompositePB->pb.usbReference, ": kNewInterfaceRef ", pCompositePB->pb.usbReference);
  451.                 pCompositePB->interfaces[pCompositePB->interfaceIndex].ref = pCompositePB->pb.usbReference;
  452.                 
  453.                 pCompositePB->pb.usbRefcon = kGetInterfaceDesc;
  454.                 break;                
  455.  
  456.             case kGetInterfaceDesc:
  457.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc result", *(long *)pCompositePB->pb.usbBuffer);
  458.  
  459.                 if(pCompositePB->pb.usbActCount < kUSBInterfaceDescriptorLength)
  460.                 {
  461.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kGetInterfaceDesc - got bad descriptor", pCompositePB->pb.usbActCount);
  462.                 }
  463.                 else
  464.                 {
  465.                 //    pCompositePB->interfaces[pCompositePB->interfaceIndex].desc = *(USBInterfaceDescriptor *)pCompositePB->pb.usbBuffer;
  466.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaces[pCompositePB->interfaceIndex].ref, 
  467.                         &pCompositePB->deviceDescriptor, pCompositePB->pb.usbBuffer, pCompositePB->deviceRef, 0);
  468.                 }
  469.                 
  470.                 /* if there's more interfaces, find them */
  471.                 pCompositePB->interfaceIndex++;
  472.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  473.                 {
  474.                     pCompositePB->pb.usbRefcon = kFindNextInterface;
  475.                 }
  476.                 else
  477.                 {
  478.                     pCompositePB->interfacesRead = true;
  479.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  480.                 }
  481.                 break;
  482.  
  483.             case kFindNextInterface:
  484.                 if(pCompositePB->currentConfiguration != pCompositePB->pb.usb.cntl.WValue)
  485.                 {
  486.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kFindNextInterface - Interface found is not in correct configuration", pCompositePB->pb.usb.cntl.WValue);
  487.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  488.                 }
  489.                 else
  490.                 {
  491.                     pCompositePB->currentInterface = pCompositePB->pb.usb.cntl.WIndex;
  492.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  493.                 }
  494.  
  495.                 break;
  496.                 
  497.             default:
  498.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  499.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  500.                 break;
  501.         }
  502.     }
  503.  
  504.     if ( !(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending))
  505.     {
  506.         CompositeDeviceInitiateTransaction(pb);
  507.     }
  508.  
  509. }
  510.  
  511. // entry points, moved from CompositeDriverDescription.c
  512.  
  513. // hubDriverInitInterface function
  514. // Called to initialize driver for an individual interface - either by expert or
  515. // internally by driver
  516. OSStatus CompositeDriverInitInterface(
  517.             UInt32                         interfaceNum, 
  518.             USBInterfaceDescriptor        *interfaceDesc, 
  519.             USBDeviceDescriptor            *deviceDesc, 
  520.             USBDeviceRef                 device)
  521. {
  522. #pragma unused (interfaceNum)
  523. #pragma unused (interfaceDesc)
  524. #pragma unused (deviceDesc)
  525. #pragma unused (device)
  526.  
  527.     return (OSStatus)kUSBNoErr;
  528. }
  529.  
  530.  
  531. static OSStatus removeInterfaces(void)
  532. {
  533. OSStatus    myErr;
  534. OSStatus     status = kUSBNoErr;
  535. static    UInt32    interfacenum = 0;
  536.  
  537.     newInterfacesPB.driverRemovalPending = true;
  538.     
  539.     if (interfacenum == 0)
  540.         newInterfacesPB.pb.usbStatus = kUSBNoErr;
  541.     
  542.     if (newInterfacesPB.pb.usbStatus == kUSBPending)
  543.     {
  544.         USBExpertStatusLevel(5, newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for Dispose/Deallocate to complete", newInterfacesPB.pb.usbRefcon);
  545.         status = kUSBInternalErr;
  546.     }
  547.     else
  548.     {
  549.         if (interfacenum < newInterfacesPB.interfaceCount)        
  550.         {
  551.             USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaces[interfacenum].ref);
  552.             InitParamBlock(newInterfacesPB.interfaces[interfacenum].ref, &newInterfacesPB.pb);
  553.             newInterfacesPB.pb.usbRefcon = 0;             
  554.             newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  555.             myErr = USBDisposeInterfaceRef(&newInterfacesPB.pb);
  556.             if(immediateError(myErr))
  557.             {
  558.                 USBExpertFatalError(newInterfacesPB.interfaces[interfacenum].ref, kUSBInternalErr, kCompositeDriverName" - USBDisposeInterfaceRef - immediate error", myErr);
  559.             }
  560.             interfacenum++;
  561.             status = kUSBDeviceBusy;
  562.         }
  563.         else
  564.         {
  565.             if (newInterfacesPB.interfaces)
  566.             {
  567.                 InitParamBlock(newInterfacesPB.deviceRef, &newInterfacesPB.pb);
  568.                 newInterfacesPB.pb.usbRefcon = 0;             
  569.                 newInterfacesPB.pb.usbBuffer = newInterfacesPB.interfaces;        
  570.                 newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  571.                 myErr = USBDeallocMem(&newInterfacesPB.pb);
  572.                 if(myErr != noErr)
  573.                 {
  574.                     USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": error disposing descriptors", myErr);
  575.                 }
  576.                 newInterfacesPB.interfaces = nil;
  577.             }
  578.             interfacenum = 0;    // Ready for next time
  579.             status = noErr;
  580.         }
  581.     }
  582.     return(status);
  583. }
  584.  
  585. OSStatus    CompositeDriverNotifyProc(UInt32     notification, void *pointer, UInt32 refcon)
  586. {
  587. OSStatus     status = kUSBNoErr;
  588. UInt32        count = 0;
  589. USBPB *pb;
  590.  
  591.     switch (notification)
  592.     {
  593.         case kNotifyChildMessage:
  594.             USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": child message from", refcon);
  595.             pb = pointer;
  596.             if (newInterfacesPB.pb.usbRefcon & kCompletionPending)
  597.             {
  598.                 USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": busy for child message", pb->usb.hub.Request);
  599.                 status = kUSBDeviceBusy;
  600.             }
  601.             else
  602.             {
  603.                 if(pb->usb.hub.Request == kUSBHubPortResetRequest)
  604.                 {
  605.                     newInterfacesPB.expertTerminatePending = true;
  606.                     do{
  607.     debugStatus(newInterfacesPB.deviceRef, kCompositeDriverName", Reset: Removing interfaces", 0);
  608.                         status = removeInterfaces();
  609.                     }while(status == kUSBDeviceBusy);
  610.                     
  611.                     if(status == noErr)
  612.                     {
  613.     debugStatus(newInterfacesPB.deviceRef, kCompositeDriverName", Reset: Interfaces removed", 0);
  614.                         newInterfacesPB.expertTerminatePending = false;
  615.                         newInterfacesPB.driverRemovalPending = false;
  616.                         newInterfacesPB.pb.usbRefcon = kResetDevice;            /* Start out at first state */
  617.                         CompositeDeviceInitiateTransaction(&newInterfacesPB.pb);
  618.                     }
  619.                     else
  620.                     {
  621.                         USBExpertStatusLevel(1, newInterfacesPB.deviceRef, kCompositeDriverName": error during driver remove", status);
  622.                     }
  623.                 }
  624.                 else
  625.                 if(pb->usb.hub.Request == kUSBHubPortSuspendRequest)
  626.                 {
  627.                     if(newInterfacesPB.interfaceCount > 1)
  628.                     {
  629.                         USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": could not suspend with multipleinterfaces", newInterfacesPB.interfaceCount);                        
  630.                         status = kUSBUnknownDeviceErr;
  631.                     }
  632.                     else
  633.                     {
  634.                         USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": passing single suspend request up", newInterfacesPB.interfaceCount);                        
  635.                         // If there is one interface, send this message to parent of the composite device (hub)
  636.                         status = kUSBUnknownRequestErr;    // Use this as a signal to tel USL to send it on
  637.                     }
  638.                 }
  639.                 else
  640.                 {
  641.                     USBExpertStatusLevel(1, newInterfacesPB.deviceRef, kCompositeDriverName": unknown child message", pb->usb.hub.Request);
  642.                     status = kUSBUnknownRequestErr;
  643.                 }
  644.             }
  645.         
  646.             break;
  647.  
  648.             
  649.         case kNotifyExpertTerminating:                                // TCC <USB15>
  650.                 newInterfacesPB.expertTerminatePending = true;
  651.                 while (count < newInterfacesPB.interfaceCount)
  652.                         USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaces[count++].ref);
  653.                 return(noErr);
  654.             break;
  655.         case kNotifyDriverBeingRemoved:
  656.             newInterfacesPB.driverRemovalPending = true;
  657.             
  658.             if (newInterfacesPB.pb.usbRefcon & kCompletionPending)
  659.             {
  660.                 USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for transaction to complete", newInterfacesPB.pb.usbRefcon);
  661.                 status = kUSBDeviceBusy;
  662.             }
  663.             else
  664.             {
  665.                 status  = removeInterfaces();
  666.             }
  667.             break;
  668.             
  669.         default:
  670.             break;
  671.     }
  672.     return status;
  673. }
  674.  
  675. // Hardware Validation
  676. // Called upon load by Expert
  677. OSStatus CompositeDriverValidateHW(USBDeviceRef device, USBDeviceDescriptor *desc)
  678. {
  679. #pragma unused (device)
  680. #pragma unused (desc)
  681.  
  682.     return (OSStatus)kUSBNoErr;
  683. }
  684.  
  685. // Initialization function
  686. // Called upon load by Expert
  687. OSStatus     CompositeDriverInitialize (USBDeviceRef device, USBDeviceDescriptorPtr pDesc,  UInt32 busPowerAvailable)
  688. {
  689.     // don't let a race condition occur; prevent finalizing until we're all done.
  690.     DeviceInitialize(device, pDesc, busPowerAvailable);
  691.     return (OSStatus)kUSBNoErr;
  692. }
  693.  
  694. // Termination function
  695. // Called by Expert when driver is being shut down
  696. OSStatus CompositeDriverFinalize(USBDeviceRef theDeviceRef, USBDeviceDescriptorPtr pDesc)
  697. {
  698. #pragma unused (pDesc)
  699.  
  700.     USBExpertStatus(theDeviceRef, kCompositeDriverName" - Finalize", 0);
  701.     return (OSStatus)kUSBNoErr;
  702. }
  703.  
  704. void DeviceInitialize(USBDeviceRef device, USBDeviceDescriptorPtr pDeviceDescriptor, UInt32 busPowerAvailable)
  705. {
  706. static Boolean beenThereDoneThat = false;
  707. UInt32 errataBits;
  708.  
  709.     if(beenThereDoneThat)
  710.     {
  711.         USBExpertFatalError(device, kUSBInternalErr, kCompositeDriverName" is not reentrant!", 0);
  712.         return;
  713.     }
  714.     beenThereDoneThat = true;
  715.     
  716.     newInterfacesPB.driverRemovalPending = false;
  717.     newInterfacesPB.expertTerminatePending = false;
  718.     
  719.     newInterfacesPB.deviceRef = device;    
  720.     newInterfacesPB.deviceDescriptor = *pDeviceDescriptor;    
  721.     
  722.     newInterfacesPB.busPowerAvailable = busPowerAvailable;                            
  723.     newInterfacesPB.delayLevel = 0;                            
  724.     newInterfacesPB.transDepth = 0;                            
  725.     newInterfacesPB.retryCount = kCompositeRetryCount;
  726.     
  727.     InitParamBlock(device, &newInterfacesPB.pb);
  728.  
  729.     errataBits = GetErrataBits(pDeviceDescriptor);
  730.     if(errataBits != 0)
  731.     {
  732.         USBExpertStatusLevel(3, device, kCompositeDriverName"Using errata:", errataBits);
  733.     }
  734.  
  735.     if((USBGetVersion() & 0xfff00000) == 0x01300000)    // 1.3.(5|6) had the hub reset memory corruption bug
  736.     {                                        // refuse to run mismatched and ROM driver will be used.
  737.         USBExpertStatusLevel(1,device, kCompositeDriverName" - DeviceInitialize not resetting due to version conflict", USBGetVersion());
  738.         USBExpertStatusLevel(1,device, "\pUSB Device Extension is not paired with correct USB Support, USB may be flaky", 0);
  739.         errataBits |= kErrataNoReset;
  740.     }
  741.  
  742.  
  743.     if( (errataBits & kErrataNoReset) != 0)
  744.     {
  745.         newInterfacesPB.pb.usbRefcon = kGetAConfiguration;    /* Start out at first state which isn't reset */
  746.     }
  747.     else
  748.     {
  749.         newInterfacesPB.pb.usbRefcon = kResetDevice;            /* Start out at first state */
  750.     }
  751.     
  752. //    DebugStr("\pIn Composite Driver");
  753.     CompositeDeviceInitiateTransaction(&newInterfacesPB.pb);
  754. }
  755.  
  756.  
  757.